package com.jiangnan.warehouse_management.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jiangnan.warehouse_management.dto.response.RecordStatsResponse;
import com.jiangnan.warehouse_management.mapper.InboundRecordMapper;
import com.jiangnan.warehouse_management.mapper.ItemMapper;
import com.jiangnan.warehouse_management.mapper.OutboundRecordMapper;
import com.jiangnan.warehouse_management.pojo.InboundRecord;
import com.jiangnan.warehouse_management.pojo.Item;
import com.jiangnan.warehouse_management.pojo.OutboundRecord;
import com.jiangnan.warehouse_management.service.RecordStatsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RecordStatsServiceImpl implements RecordStatsService {
    private final InboundRecordMapper inboundRecordMapper;
    private final OutboundRecordMapper outboundRecordMapper;
    private final ItemMapper itemMapper;

    @Override
    public RecordStatsResponse getRecordStats(String timeRange, String startDate, String endDate) {
        // 1. 计算时间范围
        Timestamp start = null, end = null;
        LocalDateTime now = LocalDateTime.now();
        if (timeRange != null) {
            switch (timeRange) {
                case "day" -> {
                    start = Timestamp.valueOf(now.toLocalDate().atStartOfDay());
                    end = Timestamp.valueOf(now.toLocalDate().plusDays(1).atStartOfDay());
                }
                case "week" -> {
                    start = Timestamp.valueOf(now.toLocalDate().minusDays(now.getDayOfWeek().getValue() - 1).atStartOfDay());
                    end = Timestamp.valueOf(now.toLocalDate().plusDays(8 - now.getDayOfWeek().getValue()).atStartOfDay());
                }
                case "month" -> {
                    start = Timestamp.valueOf(now.withDayOfMonth(1).toLocalDate().atStartOfDay());
                    end = Timestamp.valueOf(now.plusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay());
                }
                case "year" -> {
                    start = Timestamp.valueOf(now.withDayOfYear(1).toLocalDate().atStartOfDay());
                    end = Timestamp.valueOf(now.plusYears(1).withDayOfYear(1).toLocalDate().atStartOfDay());
                }
                case "custom" -> {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    if (startDate != null) {
                        start = Timestamp.valueOf(LocalDate.parse(startDate, formatter).atStartOfDay());
                    }
                    if (endDate != null) {
                        end = Timestamp.valueOf(LocalDate.parse(endDate, formatter).plusDays(1).atStartOfDay());
                    }
                }
            }
        }
        // 2. 查询入库记录
        LambdaQueryWrapper<InboundRecord> inWrapper = new LambdaQueryWrapper<>();
        if (start != null) inWrapper.ge(InboundRecord::getInboundTime, start);
        if (end != null) inWrapper.lt(InboundRecord::getInboundTime, end);
        List<InboundRecord> inList = inboundRecordMapper.selectList(inWrapper);
        // 3. 查询出库记录
        LambdaQueryWrapper<OutboundRecord> outWrapper = new LambdaQueryWrapper<>();
        if (start != null) outWrapper.ge(OutboundRecord::getOutboundTime, start);
        if (end != null) outWrapper.lt(OutboundRecord::getOutboundTime, end);
        List<OutboundRecord> outList = outboundRecordMapper.selectList(outWrapper);
        // 4. 统计
        int inboundTotal = inList.size();
        int inboundQuantity = inList.stream().mapToInt(r -> r.getQuantity() == null ? 0 : r.getQuantity()).sum();
        double inboundAmount = inList.stream().mapToDouble(r -> r.getTotalAmount() == null ? 0.0 : r.getTotalAmount()).sum();
        int outboundTotal = outList.size();
        int outboundQuantity = outList.stream().mapToInt(r -> r.getQuantity() == null ? 0 : r.getQuantity()).sum();
        double outboundAmount = outList.stream().mapToDouble(r -> r.getTotalAmount() == null ? 0.0 : r.getTotalAmount()).sum();
        // 5. top 入库物品
        Map<Integer, Integer> inItemMap = new HashMap<>();
        for (InboundRecord r : inList) {
            inItemMap.put(r.getItemId(), inItemMap.getOrDefault(r.getItemId(), 0) + (r.getQuantity() == null ? 0 : r.getQuantity()));
        }
        List<RecordStatsResponse.TopItem> topInboundItems = inItemMap.entrySet().stream()
                .sorted((a, b) -> b.getValue() - a.getValue())
                .limit(5)
                .map(e -> {
                    RecordStatsResponse.TopItem ti = new RecordStatsResponse.TopItem();
                    ti.setItemId(e.getKey());
                    Item item = itemMapper.selectById(e.getKey());
                    ti.setItemName(item != null ? item.getItemName() : null);
                    ti.setQuantity(e.getValue());
                    return ti;
                }).collect(Collectors.toList());
        // 6. top 出库物品
        Map<Integer, Integer> outItemMap = new HashMap<>();
        for (OutboundRecord r : outList) {
            outItemMap.put(r.getItemId(), outItemMap.getOrDefault(r.getItemId(), 0) + (r.getQuantity() == null ? 0 : r.getQuantity()));
        }
        List<RecordStatsResponse.TopItem> topOutboundItems = outItemMap.entrySet().stream()
                .sorted((a, b) -> b.getValue() - a.getValue())
                .limit(5)
                .map(e -> {
                    RecordStatsResponse.TopItem ti = new RecordStatsResponse.TopItem();
                    ti.setItemId(e.getKey());
                    Item item = itemMapper.selectById(e.getKey());
                    ti.setItemName(item != null ? item.getItemName() : null);
                    ti.setQuantity(e.getValue());
                    return ti;
                }).collect(Collectors.toList());
        // 7. 组装响应
        RecordStatsResponse resp = new RecordStatsResponse();
        resp.setInboundTotal(inboundTotal);
        resp.setInboundQuantity(inboundQuantity);
        resp.setInboundAmount(inboundAmount);
        resp.setOutboundTotal(outboundTotal);
        resp.setOutboundQuantity(outboundQuantity);
        resp.setOutboundAmount(outboundAmount);
        resp.setTopInboundItems(topInboundItems);
        resp.setTopOutboundItems(topOutboundItems);
        return resp;
    }
} 